#include <GameEngine/Gameplay/Objects/object_container.h>

#include <GameEngine/Gameplay/Objects/object_inventory.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

#ifndef DOXYGEN_IGNORE
#include "object_container.moc"
#endif

//=================================================================================


GAMEENGINE_IMPLEMENT_RTTI(ObjectContainer)

//! Default constructor
ObjectContainer::ObjectContainer() : Object() {}

//! Copy constructor
/*!
 @param rhs The object to copy
 */
ObjectContainer::ObjectContainer(const ObjectContainer& rhs) : Object(rhs) {}

//! Assignment operator
/*!
 @param rhs The object to copy
 */
ObjectContainer& ObjectContainer::operator=(const ObjectContainer& rhs) {
	if ( &rhs != this ) {
		Object::operator=(rhs);
	}
	return *this;
}

//! Destructor
ObjectContainer::~ObjectContainer() {}

//! Accessor to the content of the container (read only)
/*!
 @return A constant reference to the content of the container
 */
const ObjectContainer::InventoryList& ObjectContainer::inventory() const {
	return inventory_;
}

//! Accessor to the lock state of the container (read only)
/*!
 @return A constant reference to the lock state of the container
 */
const LockState& ObjectContainer::lock_state() const {
	return lock_state_;
}

//! Accessor to the lock state of the container (read-write)
/*!
 @return A reference to the lock state of the container
 */
LockState& ObjectContainer::lock_state() {
	return lock_state_;
}

//! Add an item to the inventory
/*!
 @param object The object to add to the inventory
 @param notify_object If set to true, the added object is notified of its
                      new container
 @return True if object could be added, false otherwise. Object is not
         added if it already belonged to the inventory
 */
bool ObjectContainer::add(ObjectInventory* object, bool notify_object) {
	if ( object == nil ) return false;
	if ( find(object) ) return false;
	inventory_.insert(object);
	if ( notify_object ) object->set_container(this, false);
	emit object_added(object);
	return true;
}

//! Remove an item from the inventory
/*!
 @param object The object to remove from the inventory
 @param notify_object If set to true, the removed object is notified of its
                      removal from the container
 @return True if object could be removed, false otherwise. Object is not
         removed if it did not belong to the inventory
 */
bool ObjectContainer::remove(ObjectInventory* object, bool notify_object) {
	if ( object == nil ) return false;
	if ( find(object) == false ) return false;
	if ( inventory_.remove(object) == false ) return false;
	if ( notify_object ) object->set_container(nil, false);
	emit object_removed(object);
	return true;
}

//! Find an item in the inventory
/*!
 @param object The object to find in the inventory
 @return True if object could be found, false otherwise
 */
bool ObjectContainer::find(ObjectInventory* object) const {
	return inventory_.contains(object);
}

//! Compute the weight of all objects in the inventory
/*!
 @return The weight of all objects in the inventory
 */
int ObjectContainer::total_weight() const {
	int res = 0;
	for ( InventoryList::const_iterator it = inventory_.begin(); it != inventory_.end(); ++it ) {
		res += (*it)->weight();
	}
	return res;
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
